﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.ComponentModel;
using libConn;

namespace ApartmentSale
{
    public class ReceiptView : INotifyPropertyChanged, ICloneable
    {
        private int _receipt_id;
        public int receipt_id
        {
            get
            {
                return _receipt_id;
            }
            set
            {
                _receipt_id = value;
                NotifyPropertyChanged("receipt_id");
            }
        }

        private string _receipt_code;
        public string receipt_code
        {
            get
            {
                return _receipt_code;
            }
            set
            {
                _receipt_code = value;
                NotifyPropertyChanged("receipt_code");
            }
        }

        private int _receipt_status;
        public int receipt_status
        {
            get
            {
                return _receipt_status;
            }
            set
            {
                _receipt_status = value;
            }
        }

        private double _receipt_amount;
        public double receipt_amount
        {
            get
            {
                return _receipt_amount;
            }
            set
            {
                _receipt_amount = value;
                NotifyPropertyChanged("receipt_amount");
            }
        }

        private int _receipt_type;
        public int receipt_type
        {
            get
            {
                return _receipt_type;
            }
            set
            {
                _receipt_type = value;
                NotifyPropertyChanged("receipt_type");
            }
        }

        private double _receipt_cash_amount;
        public double receipt_cash_amount
        {
            get
            {
                return _receipt_cash_amount;
            }
            set
            {
                _receipt_cash_amount = value;
                NotifyPropertyChanged("receipt_cash_amount");
            }
        }

        private double _receipt_card_amount;
        public double receipt_card_amount
        {
            get
            {
                return _receipt_card_amount;
            }
            set
            {
                _receipt_card_amount = value;
                NotifyPropertyChanged("receipt_card_amount");
            }
        }

        private double _receipt_check_amount;
        public double receipt_check_amount
        {
            get
            {
                return _receipt_check_amount;
            }
            set
            {
                _receipt_check_amount = value;
                NotifyPropertyChanged("receipt_check_amount");
            }
        }

        private string _receipt_custom_name;
        public string receipt_custom_name
        {
            get
            {
                return _receipt_custom_name;
            }
            set
            {
                _receipt_custom_name = value;
                NotifyPropertyChanged("receipt_custom_name");
            }
        }

        private DateTime _receipt_date;
        public DateTime receipt_date
        {
            get
            {
                return _receipt_date;
            }
            set
            {
                _receipt_date = value;
                NotifyPropertyChanged("receipt_date");
            }
        }

        private int _apartment_id;
        public int apartment_id
        {
            get
            {
                return _apartment_id;
            }
            set
            {
                _apartment_id = value;
                NotifyPropertyChanged("apartment_id");
            }
        }

        public string status_string
        {
            get
            {
                switch (receipt_status)
                {
                    case 0:
                        return "Normal";
                    case 1:
                        return "Cancel out";
                    case 2:
                        return "Return";
                    case 3:
                        return "Invalid";
                }
                return "Unknown";
            }
            set
            {
                switch (value)
                {
                    case "Normal":
                        receipt_status = 0;
                        break;
                    case "Cancel out":
                        receipt_status = 1;
                        break;
                    case "Return":
                        receipt_status = 0;
                        break;
                    case "Invalid":
                        receipt_status = 1;
                        break;
                    default:
                        receipt_status = 0;
                        break;
                }
            }
        }

        public string type_string
        {
            get
            {
                switch (receipt_type)
                {
                    case 0:
                        return "Affirmance";
                    case 1:
                        return "Deposit";
                    case 2:
                        return "Apartment";
                    case 3:
                        return "Decorating";
                }
                return "Affirmance";
            }
            set
            {
                switch (value)
                {
                    case "Affirmance":
                        receipt_type = 0;
                        break;
                    case "Deposit":
                        receipt_type = 1;
                        break;
                    case "Apartment":
                        receipt_type = 2;
                        break;
                    case "Decorating":
                        receipt_type = 3;
                        break;
                    default:
                        receipt_type = 0;
                        break;
                }
            }
        }

        public string date_string
        {
            get
            {
                return receipt_date.ToShortDateString();
            }
        }

        public bool has_changed { get; set; }

        public string apartment_code { get; set; }

        public ReceiptView(DataRow r)
        {
            receipt_id = Convert.ToInt32(r["receipt_id"]);
            receipt_code = Convert.ToString(r["receipt_code"]).Replace("''","'");
            receipt_status = Convert.ToInt32(r["receipt_status"]);
            receipt_amount = Convert.ToDouble(r["receipt_amount"]);
            receipt_type = Convert.ToInt32(r["receipt_type"]);
            receipt_cash_amount = Convert.ToDouble(r["receipt_cash_amount"]);
            receipt_card_amount = Convert.ToDouble(r["receipt_card_amount"]);
            receipt_check_amount = Convert.ToDouble(r["receipt_check_amount"]);
            receipt_custom_name = Convert.ToString(r["receipt_custom_name"]).Replace("''", "'");
            receipt_date = Convert.ToDateTime(r["receipt_date"]);
            apartment_id = Convert.ToInt32(r["apartment_id"]);

            Datarow = r;
            has_changed = false;
        }

        public ReceiptView()
        {
            receipt_id = 0;
            receipt_code = "";
            receipt_status = 0;
            receipt_amount = 0;
            receipt_type = 0;
            receipt_cash_amount = 0;
            receipt_card_amount = 0;
            receipt_check_amount = 0;
            receipt_custom_name = "";
            receipt_date = DateTime.Now;
            apartment_id = 0;

            initDataRow();
            has_changed = false;
        }

        private DataRow _datarow;
        public DataRow Datarow
        {
            set
            {
                _datarow = value;
            }
            get
            {
                refreshDataRow();
                return _datarow;
            }
        }

        public string queryString
        {
            get
            {
                return "SELECT * FROM receipt WHERE receipt_id = " + receipt_id;
            }
        }
        public string deleteString
        {
            get
            {
                return "DELETE FROM receipt WHERE receipt_id = " + receipt_id;
            }
        }

        public readonly string tableName = "receipt";
        public readonly int ColumnCount = 11;

        private void initDataRow()
        {
            string errMessage = "";
            DataTable table = AccdbConn.query(queryString, ref errMessage);
            Datarow = table.NewRow();
        }

        private void refreshDataRow()
        {
            DataRow r = _datarow;
            r["receipt_id"] = receipt_id;
            r["receipt_code"] = receipt_code.Replace("'", "''");
            r["receipt_status"] = receipt_status;
            r["receipt_amount"] = receipt_amount;
            r["receipt_type"] = receipt_type;
            r["receipt_cash_amount"] = receipt_cash_amount;
            r["receipt_card_amount"] = receipt_card_amount;
            r["receipt_check_amount"] = receipt_check_amount;
            r["receipt_custom_name"] = receipt_custom_name.Replace("'", "''");
            r["receipt_date"] = receipt_date;
            r["apartment_id"] = apartment_id;
        }

        public string Insert()
        {
            string errMessage = "";

            if (!AccdbConn.insert(queryString, tableName, ColumnCount, Datarow, ref errMessage))
            {
                errMessage = "Add receipts failed.\n" + errMessage;
                has_changed = true;
            }
            else
            {
                has_changed = false;
            }

            return errMessage;
        }

        public string Update()
        {
            string errMessage = "";

            if (!AccdbConn.update(queryString, tableName, ColumnCount, Datarow, ref errMessage))
            {
                errMessage = "Modify the receipt failed.\n" + errMessage;
                has_changed = true;
            }
            else
            {
                has_changed = false;
            }

            return errMessage;
        }

        public string Delete()
        {
            string errMessage = "";
            AccdbConn.exec(deleteString, ref errMessage);

            if (errMessage != "")
                errMessage = "Remove the receipt failed.\n" + errMessage;

            return errMessage;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                has_changed = true;
            }
        }

        public object Clone()
        {
            return new ReceiptView(Datarow);
        }
    }

    public class ReceiptComputer
    {
        private const int TYPE_COUNT = 4;
        private List<ReceiptView> receipts;

        private int[] typeGrid;
        public int[] TypeGrid
        {
            get { return typeGrid; }
        }

        public ReceiptComputer()
        {
            receipts = new List<ReceiptView>();
            typeGrid = new int[TYPE_COUNT];

            for (int i = 0; i < TYPE_COUNT; i++)
            {
                typeGrid[i] = 0;
            }
        }

        public void Add(ReceiptView receipt)
        {
            receipts.Add(receipt);
            if (receipt.receipt_status < 2)
                typeGrid[receipt.receipt_type]++;
        }

        public double GetReceiptTotal()
        {
            double Total = 0;
            foreach (ReceiptView receipt in receipts)
            {
                if (receipt.receipt_status < 2)
                {
                    Total += receipt.receipt_amount;
                }
            }
            return Total;
        }

        public double GetAffirmanceRebate()
        {
            double Total = 0;
            double amount = 0;
            foreach (ReceiptView receipt in receipts)
            {
                if (receipt.receipt_type == 0 && receipt.receipt_status < 2)
                {
                    amount = getAffirmance(receipt.receipt_id);
                    if (amount != -1)
                    {
                        Total += amount;
                    }
                }
            }
            return Total;
        }

        private double getAffirmance(int receipt_id)
        {
            string errMessage = null;
            string str = "SELECT * FROM affirmance WHERE receipt_id = " + receipt_id;

            DataTable oleDT;
            oleDT = libConn.AccdbConn.query(str, ref errMessage);

            if (errMessage != null)
            {
                System.Windows.MessageBox.Show(
                    errMessage,
                    "An error occurred while reading data affirmance.",
                    System.Windows.MessageBoxButton.OK,
                    System.Windows.MessageBoxImage.Error);
                return -1;
            }

            if (oleDT.Rows.Count != 1)
            {
                System.Windows.MessageBox.Show(
                    "The same ID exists in the database records of affirmance.",
                    "An error occurred while reading data affirmance.",
                    System.Windows.MessageBoxButton.OK,
                    System.Windows.MessageBoxImage.Error);
                return -1;
            }

            DataRow r = oleDT.Rows[0];

            return Convert.ToDouble(r["affirmance_rule_rebate_amount"]);
        }
    }
}
